<script lang="ts" setup>
import type { AddFormType, AddType, DeleteType, UpdataType } from './types';

import type { VxeGridListeners, VxeGridProps } from '#/adapter/vxe-table';

import { Page, useVbenModal } from '@vben/common-ui';
import { cloneDeep } from '@vben/utils';

import { Button, MenuItem, message, Modal, Switch } from 'ant-design-vue';

import { useVbenVxeGrid } from '#/adapter/vxe-table';
import {
  deleteAdminMenus,
  getAdminMenus,
  postAdminMenusImport,
  postAdminMenusLangExport,
  postAdminMenusListOrder,
  putAdminMenus,
} from '#/api/admin/menus';
import ButtonAction from '#/components/ButtonAction';
import Icon from '#/components/Icons';
import { resetRoutes } from '#/router';
import { handleTree, sortByField, toggleStatus } from '#/utils';

import { FormModalView } from './components';

defineOptions({
  name: 'AdminMenu',
});
const router = useRouter();
const routeMeta = router.currentRoute.value.meta;
const viewTitle = routeMeta.title.replace('管理', '');
const menuList: any = ref([
  {
    id: 0,
  },
]);
const importLoading = ref(false);
const nextApp = ref('');
const exportLoading = ref(false);
const gridOptions: VxeGridProps<UpdataType> = {
  rowConfig: {
    useKey: true,
    drag: true,
  },
  columnConfig: {
    useKey: true,
  },
  treeConfig: {
    parentField: 'parent_id',
    rowField: 'id',
    transform: true,
  },
  pagerConfig: {
    enabled: false,
  },
  columns: [
    { title: '序号', type: 'seq', width: 50, dragSort: true },
    { field: 'name', title: '菜单名称', treeNode: true },
    { field: 'list_order', title: '排序' },
    { field: 'icon', title: '图标' },
    { field: 'path', title: '路径', slots: { default: 'path' } },
    { field: 'status', title: '状态', slots: { default: 'status' } },
    { field: 'remark', title: '备注' },
    {
      slots: { default: 'action' },
      field: 'action',
      fixed: 'right',
      title: '操作',
      width: 240,
    },
  ],
  height: 'auto',
  keepSource: true,
  proxyConfig: {
    ajax: {
      query: async () => {
        const { data } = await getAdminMenus();
        data.list = sortByField(data.list, 'list_order').filter(
          (item: any) =>
            (item.type !== 2 && item.status) ||
            item.parent_id === 0 ||
            item.controller === 'Dev',
        );
        menuList.value = data.list;
        data.total = 0;
        return data;
      },
    },
  },
  toolbarConfig: {
    custom: true,
    // export: true,
    // import: true,
    refresh: true,
    zoom: true,
  },
};

const [Grid, GridApi] = useVbenVxeGrid({
  gridOptions,
});

const gridEvents: VxeGridListeners<UpdataType> = {
  async rowDragend() {
    const visibleData = await GridApi.grid.getTableData().visibleData;
    const result: { [key: string]: number } = {};
    // 使用 forEach 替代 reduce
    visibleData.forEach((item, index) => {
      result[item.id] = index;
    });
    await postAdminMenusListOrder({ list_orders: result });
    resetRoutes();
  },
};

const handleDelete = async (row: DeleteType) => {
  const $table = GridApi.grid;
  if ($table) {
    const { msg } = await deleteAdminMenus(row.id);
    $table.remove(row);
    message.success(msg);
  }
};

const onChange = async (row: UpdataType) => {
  Modal.confirm({
    title: '系统提示',
    content: `确认要${row.status === 0 ? '停用' : '启用'}${row.name}吗?`,
    async onOk() {
      try {
        await putAdminMenus(row.id, row);
        message.success(`已${row.status === 0 ? '停用' : '启用'}${row.name}`);
        resetRoutes();
      } catch {
        row.status = toggleStatus(row.status);
      }
    },
    onCancel() {
      row.status = toggleStatus(row.status);
    },
  });
};

const [FormModal, formModalApi] = useVbenModal({
  // 连接抽离的组件
  connectedComponent: FormModalView,
  onClosed() {
    const formModalData = formModalApi.getData();
    if (formModalData?.isUpdata) {
      GridApi.query();
      resetRoutes();
    }
  },
});
function formatHigherDeptOptions(treeList: any): any {
  // 根据返回数据的status字段值判断追加是否禁用disabled字段，返回处理后的树结构，用于上级菜单级联选择器的展示（实际开发中也是如此，不可能前端需要的每个字段后端都会返回，这时需要前端自行根据后端返回的某些字段做逻辑处理）
  if (!treeList || treeList.length === 0) return;
  const newTreeList = [];
  for (const element of treeList) {
    if (element.controller !== 'Dev') {
      element.disabled = element.status === 0;
    }
    formatHigherDeptOptions(element.children);

    newTreeList.push(element);
  }
  return newTreeList;
}
const openDialog = async (
  title: '新增' | '新增子菜单' | '编辑',
  row?: AddType | null,
) => {
  formModalApi.setState({
    title: `${title}${viewTitle}`,
  });
  const menus = formatHigherDeptOptions(
    handleTree(cloneDeep(menuList.value), 'id', 'parent_id'),
  );
  let form: AddFormType = {};

  if (row && title === '编辑') {
    form = cloneDeep(row);
    form.icon = form.icon ? `fa:${form.icon}` : '';
  }
  if (row && title === '新增子菜单') {
    form.parent_id = row.id;
    form.app = row.app;
  }
  formModalApi.setData({
    form,
    menus: [{ id: 0, name: '一级导航', children: [] }, ...menus],
  });

  formModalApi.open();
};

async function handleImportMenu() {
  importLoading.value = true;
  try {
    const { data } = await postAdminMenusImport({ app: nextApp.value });
    if (data.next_app) {
      nextApp.value = data.next_app;
      await handleImportMenu();
    } else {
      importLoading.value = false;
      message.success('菜单导入成功！');
      await GridApi.query();
      resetRoutes();
    }
  } catch {
    importLoading.value = false;
  }
}

async function handleExportLanguage() {
  exportLoading.value = true;
  const { msg } = await postAdminMenusLangExport();

  exportLoading.value = false;
  message.success(msg);
}
</script>

<template>
  <Page auto-content-height>
    <FormModal />
    <Grid :grid-events="gridEvents" :table-title="`${viewTitle}列表`">
      <template #toolbar-tools>
        <Button class="mr-2" type="primary" @click="openDialog('新增')">
          <span class="anticon">
            <Icon icon="ri:add-line" />
          </span>
          新增{{ viewTitle }}
        </Button>
        <Button
          :loading="importLoading"
          class="mr-2"
          type="primary"
          @click="handleImportMenu"
        >
          <span class="anticon">
            <Icon icon="ri:hammer-line" />
          </span>
          导入新菜单
        </Button>
        <Button class="mr-2" type="primary" @click="handleExportLanguage">
          <span class="anticon">
            <Icon icon="ri:translate" />
          </span>
          导出后台菜单多语言包
        </Button>
      </template>

      <template #path="{ row }">
        {{ `${row.app}/${row.controller}/${row.action}` }}
      </template>
      <template #status="{ row }">
        <Switch
          v-model:checked="row.status"
          :checked-value="1"
          :un-checked-value="0"
          checked-children="显示"
          un-checked-children="隐藏"
          @change="onChange(row)"
        />
      </template>

      <template #action="{ row }">
        <ButtonAction
          :row="row"
          :show-data-management="true"
          @delete="handleDelete(row)"
          @edit="openDialog('编辑', row)"
        >
          <template #menuContent>
            <MenuItem>
              <Button type="link" @click="openDialog('新增子菜单', row)">
                <template #icon>
                  <span class="anticon">
                    <Icon icon="ri:add-line" />
                  </span>
                </template>
                新增子菜单
              </Button>
            </MenuItem>
          </template>
        </ButtonAction>
      </template>
    </Grid>
  </Page>
</template>
